import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { ComponentPropsType } from "@/components/QuestionComponents";
import { produce } from "immer";
import { getNextSelectedId, insertNewComponent } from "./utils";
import cloneDeep from "lodash.clonedeep";
import { nanoid } from "nanoid";
import { arrayMove } from "@dnd-kit/sortable";

export type ComponentInfoType = {
  fe_id: string;
  type: string;
  title: string;
  isHidden?: boolean;
  isLocked?: boolean;
  props: ComponentPropsType;
};

export type ComponentsStateType = {
  selectedId: string;
  componentList: ComponentInfoType[];
  copiedComponent?: ComponentInfoType | null; // 保存复制的组件
};

const INIT_STATE: ComponentsStateType = {
  selectedId: "",
  componentList: [],
  copiedComponent: null,
};

const componentSlice = createSlice({
  name: "component",
  initialState: INIT_STATE,
  reducers: {
    // 重置所有组件
    resetComponents: (
      _: ComponentsStateType,
      action: PayloadAction<ComponentsStateType>
    ) => {
      return action.payload;
    },
    // 修改选中 id
    changeSelectedId: produce(
      (draft: ComponentsStateType, action: PayloadAction<string>) => {
        draft.selectedId = action.payload;
      }
    ),
    // 添加新组件
    addComponent: produce(
      (
        draft: ComponentsStateType,
        action: PayloadAction<ComponentInfoType>
      ) => {
        const newComponent = action.payload;

        insertNewComponent(draft, newComponent);
      }
    ),
    // 删除组件
    deleteComponent: produce((draft: ComponentsStateType) => {
      const { selectedId, componentList } = draft;

      const newSelectedId = getNextSelectedId(selectedId, componentList);
      draft.selectedId = newSelectedId;

      const index = componentList.findIndex((c) => c.fe_id === selectedId);
      if (index > -1) {
        componentList.splice(index, 1);
      }
    }),
    // 修改组件属性
    changeComponentProps: produce(
      (
        draft: ComponentsStateType,
        action: PayloadAction<ComponentPropsType>
      ) => {
        const { selectedId, componentList } = draft;
        const component = componentList.find((c) => c.fe_id === selectedId);
        if (component) {
          component.props = {
            ...component.props,
            ...action.payload,
          };
        }
      }
    ),
    // 隐藏和显示组件
    changeComponentHidden: produce(
      (
        draft: ComponentsStateType,
        action: PayloadAction<{ fe_id: string; isHidden: boolean }>
      ) => {
        const { componentList } = draft;
        const { fe_id, isHidden } = action.payload;

        let nextSelectedId = "";
        if (isHidden) {
          // 隐藏
          nextSelectedId = getNextSelectedId(fe_id, componentList);
        } else {
          // 显示
          nextSelectedId = fe_id;
        }
        draft.selectedId = nextSelectedId;

        const comp = componentList.find((c) => c.fe_id === fe_id);

        if (!comp) return;
        comp.isHidden = isHidden;
      }
    ),
    // 锁定/解锁
    toggleComponentLock: produce(
      (
        draft: ComponentsStateType,
        action: PayloadAction<{ fe_id: string }>
      ) => {
        const { componentList } = draft;
        const { fe_id } = action.payload;

        const comp = componentList.find((c) => c.fe_id === fe_id);
        if (!comp) return;
        comp.isLocked = !comp.isLocked;
      }
    ),
    // 拷贝
    copyComponent: produce((draft: ComponentsStateType) => {
      const { selectedId, componentList } = draft;

      const comp = componentList.find((c) => c.fe_id === selectedId);
      if (!comp) return;

      draft.copiedComponent = cloneDeep(comp);
    }),
    // 粘贴
    pasteComponent: produce((draft: ComponentsStateType) => {
      const { copiedComponent } = draft;
      if (copiedComponent) {
        copiedComponent.fe_id = nanoid();
        insertNewComponent(draft, copiedComponent);
      }
    }),
    // 选中上一个
    selectPrevComponent: produce((draft: ComponentsStateType) => {
      const { selectedId, componentList } = draft;
      const index = componentList.findIndex((c) => c.fe_id === selectedId);
      if (index <= 0) return;
      if (index > 0) {
        draft.selectedId = componentList[index - 1].fe_id;
      }
    }),
    // 选中下一个
    selectNextComponent: produce((draft: ComponentsStateType) => {
      const { selectedId, componentList } = draft;
      const index = componentList.findIndex((c) => c.fe_id === selectedId);
      if (index < 0) return;
      if (index < componentList.length - 1) {
        draft.selectedId = componentList[index + 1].fe_id;
      }
    }),
    // 修改组件标题
    changeComponentTitle: produce(
      (
        draft: ComponentsStateType,
        action: PayloadAction<{ fe_id: string; title: string }>
      ) => {
        const { componentList } = draft;
        const { fe_id, title } = action.payload;
        const comp = componentList.find((c) => c.fe_id === fe_id);
        if (!comp) return;
        comp.title = title;
      }
    ),
    // 移动组件位置
    moveComponent: produce(
      (
        draft: ComponentsStateType,
        action: PayloadAction<{ oldIndex: number; newIndex: number }>
      ) => {
        const { componentList } = draft;
        const { oldIndex, newIndex } = action.payload;
        draft.componentList = arrayMove(componentList, oldIndex, newIndex);
      }
    ),
  },
});

export const {
  resetComponents,
  changeSelectedId,
  addComponent,
  deleteComponent,
  changeComponentProps,
  changeComponentHidden,
  toggleComponentLock,
  copyComponent,
  pasteComponent,
  selectPrevComponent,
  selectNextComponent,
  changeComponentTitle,
  moveComponent,
} = componentSlice.actions;

export default componentSlice.reducer;
